package com.mdp.tpa.wechat.service;
 
import java.util.Date;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.mdp.tpa.wechat.HttpRequestUtil;
import com.mdp.tpa.wechat.api.cache.AccessTokenCache;
import com.mdp.tpa.wechat.api.cache.ApiTicketCache;
import com.mdp.tpa.wechat.api.cache.JsapiTicketCache;
import com.mdp.tpa.wechat.service.cache.DefaultApiTicketCacheService;
import com.mdp.tpa.wechat.service.cache.DefaultJsapiTicketCacheService;
import com.mdp.tpa.wechat.api.AccessTokenService;
import com.mdp.tpa.wechat.api.ApiUrls;
import com.mdp.tpa.wechat.api.TicketService;
import com.mdp.tpa.wechat.config.WxpubProperties;
import com.mdp.tpa.wechat.entity.ApiTicket;
import com.mdp.tpa.wechat.entity.JsapiTicket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import com.mdp.core.err.BizException;

@Service
public class TicketServiceImpl  implements TicketService {
	 
	Log log=LogFactory.getLog(TicketServiceImpl.class);
 
	private  Lock lock = new ReentrantLock();
	
	@Autowired
    WxpubProperties properties;
	
	@Autowired(required=false)
	ApiTicketCache apiTicketCache=new DefaultApiTicketCacheService();
	
	@Autowired(required=false)
	JsapiTicketCache jsapiTicketCache=new DefaultJsapiTicketCacheService();
	 
	@Autowired
    AccessTokenService token;

	
	@Value("${mdp.wxapi.enabled-load-access-token:true}")
	boolean enabledLoadAccessToken=true;

	@Override
	public ApiTicket getApiTicket(String appid, String accessToken, boolean force) {
		String url=String.format(ApiUrls.TICKET_GET, accessToken, "wx_card");
		Map<String, Object> result= HttpRequestUtil.sendGetJson(url, null);
		if(!result.containsKey("ticket")){
			log.error(result);
			log.error("获取access_token出错，将再尝试一次向微信获取access_token");
			result=HttpRequestUtil.sendGetJson(url, null);
		}
		if(!result.containsKey("ticket")){
			log.error(result);
			//log.error("获取access_token出错，将再尝试一次向微信获取access_token");
			//result=swapTemplate.send("wxapi_accessToken_getSnsOauth2Ticket", map);
			throw new BizException(result.get("errcode")+"", (String) result.get("errmsg"));
		}
		ApiTicket token=new ApiTicket();
		token.setTicket((String) result.get("ticket"));
		token.setExpiresIn((Integer) result.get("expires_in"));
		token.setCtime((new Date()).getTime());
		apiTicketCache.put(appid, token);
		return token;
	}

	 
	
 


	@Override
	public ApiTicket getApiTicket( ) {
		
		String appid=properties.getAppid();
		ApiTicket t;
		try {
			lock.lock();
			t = this.apiTicketCache.get(appid);
			if (t == null) {
				String accessToken = token.getAccessToken().getAccessToken();
				t = this.getApiTicket(appid, accessToken, true);
			}
		} finally {
			lock.unlock();
		}
		return t;
	}







	@Override
	public JsapiTicket getJsapiTicket() {
		String appid=properties.getAppid();

		JsapiTicket t;
		lock.lock();
		try {
			t = this.jsapiTicketCache.get(appid);
			if (t == null) {
				String accessToken = token.getAccessToken().getAccessToken();
				t = this.getJsapiTicket(appid, accessToken, true);
			}
		} finally {
			lock.unlock();
		}
		return t;
	}






	@Override
	public JsapiTicket getJsapiTicket(String appid,String accessToken,boolean force) {
 
		String url=String.format(ApiUrls.TICKET_GET, accessToken, "jsapi");
		Map<String, Object> result=HttpRequestUtil.sendGetJson(url, null);
		if(!result.containsKey("ticket")){
			log.error(result);
			log.error("获取access_token出错，将再尝试一次向微信获取access_token");
			result=HttpRequestUtil.sendGetJson(url, null);
		}
		if(!result.containsKey("ticket")){
			log.error(result);
			//log.error("获取access_token出错，将再尝试一次向微信获取access_token");
			//result=swapTemplate.send("wxapi_accessToken_getSnsOauth2Ticket", map);
			throw new BizException(result.get("errcode")+"", (String) result.get("errmsg"));
		}
		JsapiTicket token=new JsapiTicket();
		token.setTicket((String) result.get("ticket"));
		token.setExpiresIn((Integer) result.get("expires_in"));
		token.setCtime((new Date().getTime()));
		jsapiTicketCache.put(appid, token);
		return token;
	} 
	 
	@Scheduled(fixedRate= AccessTokenCache.TokenCheckMilliseconds)
	void checkJsapiTicket(){   
		try {
			if( this.enabledLoadAccessToken==false) {
				return;
			}
					try { 
						Date now=new Date();
						Long nowTime=now.getTime();
						JsapiTicket jsapiTicket=jsapiTicketCache.get(properties.getAppid());
						if(jsapiTicket==null|| (nowTime-jsapiTicket.getCtime())+AccessTokenCache.TokenCheckMilliseconds*2 >= jsapiTicket.getExpiresIn()*1000 ){
							String accessToken=token.getAccessToken().getAccessToken();
							getJsapiTicket( properties.getAppid(),accessToken,true);
						} 
						
					} catch (Exception e) {
						log.error("",e); 
					}
		} catch (Exception e) {
			log.error("自动检查刷新微信jsapiTicket是否过期失败 ");  
		}
	} 
	@Scheduled(fixedRate=AccessTokenCache.TokenCheckMilliseconds,initialDelay=60000)
	void checkApiTicket(){  
		try {
					try {
						Date now=new Date();
						Long nowTime=now.getTime();
						ApiTicket apiTicket=apiTicketCache.get(properties.getAppid());
						if(apiTicket==null||  (nowTime-apiTicket.getCtime())+AccessTokenCache.TokenCheckMilliseconds*2 >= apiTicket.getExpiresIn()*1000 ){
							String accessToken=token.getAccessToken().getAccessToken();
							getApiTicket(properties.getAppid(),accessToken,true);
						}  
					} catch (Exception e) {
						log.error("自动检查刷新微信apiTicket是否过期失败 应用编号【"+properties.getAppid()+"】");
					}
		} catch (Exception e) {
			log.error("自动检查刷新微信apiTicket是否过期失败 ");  
		}
	} 
 
}
